package com.chunlin.object;

import java.util.Objects;

//Object是Java默认提供的一个类。Java里面除了Object类，所有的类都是存在继承关系的
// 默认会继承Object父类。即所有类的对象都可以使用Object的引用进行接收
//范例：使用Object接收所有类的对象
public class ObjectTest extends Object{
    public static void main(String[] args) {
//        test1();
        test2();
    }

    //在Java中，==进行比较时：
    //a.如果==左右两侧是基本类型变量，比较的是变量中值是否相同
    //b.如果==左右两侧是引用类型变量，比较的是引用变量地址是否相同
    //c.如果要比较对象中内容，必须重写Object中的equals方法，因为equals方法默认也是按照地址比较的
    public static void test2() {
        String str1 = "shengming";
        String str2 = "shengming";
        Person p1 = new Person(str1, 22);
        Person p2 = new Person(str2, 22);
        int a = 10;
        int b = 10;
        System.out.println(a == b); // 输出true
        System.out.println(p1 == p2); // 输出false
        System.out.println(p1.equals(p2)); // 重写之前输出false,重写之后输出true

        //结论：比较对象中内容是否相同的时候，一定要重写equals方法

        System.out.println(p1.hashCode()); // 重写之前输出不同,重写之后输出相同
        System.out.println(p2.hashCode());

        //结论：
        //1、hashcode方法用来确定对象在内存中存储的位置是否相同
        //2、事实上hashCode() 在散列表中才有用，在其它情况下没用
        // 在散列表中hashCode() 的作用是获取对象的散列码，进而确定该对象在散列表中的位置
    }

    public static void test1() {
        function(new Person());
        function(new Student());
    }

    public static void function(Object obj) {
        //隐式调用 toString() 方法：println 方法会检查传入的对象是否为 null，如果不是 null，它会隐式调用对象的 toString() 方法来获取字符串表示
        System.out.println(obj);

        System.out.println(obj.toString());
    }
}

class Person{
    private String name ;
    private int age ;

    public Person() {}

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (obj == this) {
            return true;
        }

        if (!(obj instanceof Person)) {
            return false;
        }

        Person person = (Person) obj;
        return this.name.equals(person.name) && this.age == person.age;
    }

    //hashCode() 方法返回一个整数，称为对象的哈希码。哈希码用于在基于哈希的数据结构中快速查找对象
    //如果两个对象根据 equals() 方法是相等的，那么它们的 hashCode() 方法必须返回相同的整数值,相反的，哈希码相同的对象不一定是相等的
    //equals() 方法用于比较两个对象的内容是否相等。默认情况下，Object 类中的 equals() 方法比较的是两个对象的内存地址，即引用是否相同
    //但在大多数情况下，我们需要重写这个方法来比较对象的实际内容
    @Override
    public int hashCode() {
        //虽然这个hash最后还是要调用hashCode这个方法,但是请注意
        // 这个方法不一定就是Object中的方法,也可以是对象重写之后的hashCode方法
        return Objects.hash(name, age);
    }
}
class Student{}